//
//  DXMLBoutObject.m
//  DerbyStatter
//
//  Created by glenn andreas on 1/6/14.
//  Copyright (c) 2014 glenn andreas. All rights reserved.
//

#import "DXMLBoutObject.h"
#import "DXMLVenueObject.h"
#import "DXMLRuleSetObject.h"
#import "DXMLTeamObject.h"
#import "DXMLPeriodObject.h"
#import "DXMLSkaterEventObject.h"
#import "DXMLJamObject.h"
#import "DXMLTimeStamp.h"
@class DXMLPeriodObject;
#ifdef notyet
static __thread void *currentBout;
#endif

@implementation DXMLBoutObject
DXMLCHILDATTR(venue,Venue, DXMLVenueObject)
DXMLCHILDRENATTR(teams, Teams, DXMLTeamObject)
DXMLCHILDRENATTR(periods, Periods, DXMLPeriodObject)

@synthesize ruleSet = _ruleSet;
- (DXMLRuleSetObject *) ruleSet
{
    if (_ruleSet)
        return _ruleSet;
    _ruleSet = [self firstChildWithElementName: [DXMLRuleSetObject elementName]];
    if (_ruleSet)
        return _ruleSet;
    // grab one based on the ruleset attribute, or use the default
    if ([self.attributes objectForKey:@"ruleset"]) {
        _ruleSet = [DXMLRuleSetObject ruleSetForName:[self.attributes objectForKey:@"ruleset"]];
    }
    if (!_ruleSet)
        _ruleSet = [DXMLRuleSetObject defaultRuleSet];
    return _ruleSet;
}
- (void) setRuleSet:(DXMLRuleSetObject *)ruleSet
{
    _ruleSet = ruleSet;
    [self setFirstChild:ruleSet withElementName:[DXMLRuleSetObject elementName]];
}

- (DXMLTeamObject *)homeTeam
{
    if (self.teams.count >= 1)
        return self.teams[0];
    return nil;
}
- (DXMLTeamObject *)awayTeam
{
    if (self.teams.count >= 2)
        return  self.teams[1];
    return nil;
}
- (DXMLTeamObject *)officials
{
    if (self.teams.count >= 3)
        return  self.teams[2];
    return nil;
}
- (DXMLPeriodObject *) firstPeriod
{
    if (self.periods.count >= 1)
        return self.periods[0];
    return nil;
}
- (DXMLPeriodObject *) secondPeriod
{
    if (self.periods.count >= 2)
        return self.periods[1];
    return nil;
}
#ifdef notyet
+ (DXMLBoutObject *) currentBout;
{
    return (__bridge DXMLBoutObject *)currentBout;
}
#endif
- (NSArray *) penaltiesForSkater: (DXMLPersonObject *) skater
{
    if (!skater) return nil;
    NSMutableArray *retval = [NSMutableArray array];
    for (DXMLPeriodObject *period in self.periods) {
        [period enumerateJams:^(DXMLJamObject *jam, BOOL *stop) {
            [jam enumerateChildren:^(DXMLEventObject *child, BOOL *stop) {
                DXMLPenaltyObject *pen = (DXMLPenaltyObject *)child;
                if (pen.skater == skater) {
                    [retval addObject:pen];
                }
            } ofClass:[DXMLPenaltyObject class]];
        }];
    }
    return retval;
}
- (NSInteger) scoreForTeam: (DXMLTeamObject *) team;
{
    __block NSInteger retval = 0;
    for (DXMLPeriodObject *period in self.periods) {
        [period enumerateJams:^(DXMLJamObject *jam, BOOL *stop) {
            [jam enumerateChildren:^(DXMLEventObject *child, BOOL *stop) {
                DXMLPassObject *pass = (DXMLPassObject *)child;
                if (pass.team == team)
                    retval += pass.score;
            } ofClass:[DXMLPassObject class]];
        }];
    }
    return retval;
}
- (NSArray *) boxTripsForSkater: (DXMLPersonObject *) skater;
{
    if (!skater) return nil;
    NSMutableArray *retval = [NSMutableArray array];
    __block NSMutableArray *pair = nil;
    __block DXMLPersonObject *sub = nil;
    for (DXMLPeriodObject *period in self.periods) {
        [period enumerateJams:^(DXMLJamObject *jam, BOOL *stop) {
            [jam enumerateChildren:^(DXMLEventObject *child, BOOL *stop) {
                if ([child isKindOfClass:[DXMLEnterBoxObject class]]) {
                    DXMLEnterBoxObject *enter = (DXMLEnterBoxObject *)child;
                    if ([enter skater] == skater) {
                        pair = [NSMutableArray arrayWithObject:enter];
                        [retval addObject:pair];
                        sub = [[enter childOfClass:[DXMLSubstitutionObject class] atIndex:0] skater]; // find a sub
                    }
                } else if ([child isKindOfClass:[DXMLExitBoxObject class]]) {
                    DXMLExitBoxObject *exit = (DXMLExitBoxObject *)child;
                    // The exit skater may be subbed
                    if ([exit skater] == skater || (sub && [exit skater] == sub)) {
                        // if there was no matching enter object, we have to
                        // ignore this
                        [pair addObject:exit];
                        pair = nil;
                    }
                }
            }];
        }];
    }
    return retval;
}
static NSString *defaultBout = @"<bout><team id='home'><!--<person name=\"Alpha\" number=\"1111\"/><person name=\"Beta\" number=\"2222\"/>--></team><team id='away'/><period number=\"1\"/><period number=\"2\"/></bout>";
+ (DXMLBoutObject *) defaultBout
{
    if (defaultBout.length) {
        DXMLImporter *importer = [[DXMLImporter alloc] initWithData: [defaultBout dataUsingEncoding:NSUTF8StringEncoding]];
        NSError *error;
        return (DXMLBoutObject *)[importer parse: &error];
    }
    return nil;
}
- (void) makeDefaultBout
{
    defaultBout = [self xmlString];
}
// bouts don't have timestamp components per spec, so
// return the date (makes it easier to use HH:MM:SS for period start times)
- (NSDate *) date
{
    NSString *date = [self attributeForKey:@"date"];
    if (!date) return [NSDate date]; // today
    NSArray *parts = [date componentsSeparatedByString:@"_"];
    if (parts.count == 3) {
        NSDateComponents *compo = [[NSDateComponents alloc] init];
        compo.year = [[parts objectAtIndex:0] integerValue];
        compo.month = [[parts objectAtIndex:1] integerValue];
        compo.day = [[parts objectAtIndex:2] integerValue];
        return [[NSCalendar currentCalendar] dateFromComponents:compo];
    } else {
        return [NSDate date]; // today
    }
}
- (void) setDate: (NSDate *) date
{
    if (!date) {
        [self setAttribute:nil forKey:@"date"];
    } else {
#ifdef NSCalendarUnitHour
        NSDateComponents *compo = [[NSCalendar currentCalendar] components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:date];
#else
        NSDateComponents *compo = [[NSCalendar currentCalendar] components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:date];
#endif
        [self setAttribute:[NSString stringWithFormat:@"%.4zd_%.2zd_%.2zd", compo.year, compo.month, compo.day] forKey:@"date"];
    }
}
- (DXMLTimestamp *) timestamp
{
    NSString *date = [self attributeForKey:@"date"];
    if (date) {
        return [[DXMLTimestamp alloc] initWithString:date forObject:self];
    }
    return nil;
}
- (void) setTimestamp:(DXMLTimestamp *)timestamp
{
    [self setDate: timestamp.date];
}
@end

@implementation DXMLObject(Bout)
- (DXMLBoutObject *) enclosingBout
{
    DXMLObject *retval = self;
    while (retval) {
        if ([retval isKindOfClass:[DXMLBoutObject class]])
            return (DXMLBoutObject *)retval;
        retval = retval.parent;
    }
    return nil;
}
@end